﻿using System;
using System.Reflection;
using System.Collections.Generic;

namespace UFrameWork
{
    public class UMethod
    {
        /// <summary>
        /// 方法信息
        /// </summary>
        public class Method
        {
            public Method(object instance, int order, MethodInfo method)
            {
                this.instance = instance;
                this.order = order;
                this.method = method;
            }

            public object instance;

            public int order;

            public MethodInfo method;
        }

        /// <summary>
        /// key值
        /// </summary>
        public string Key { get;  private set; }

        /// <summary>
        /// 方法队列
        /// </summary>
        private List<Method> list = new List<Method>();

        public UMethod(string key,object obj, MethodInfo info,int order)
        {
            Key = key;
            Add(obj,info,order);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public List<Method> Get()
        {
            return list;
        }

        /// <summary>
        /// 新增一个方法
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="info"></param>
        public void Add(object obj,MethodInfo info,int order)
        {
            Remove();
            list.Add(new Method(obj, order, info));
            Sort();
        }

        /// <summary>
        /// 程序集热更新
        /// </summary>
        /// <param name="assembly"></param>
        public void Update(Assembly assembly)
        {
            List<Method> newlist = new List<Method>();

            foreach (Method v in list)
            {
                if (v.method.GetType().Assembly.FullName != assembly.FullName)
                {
                    newlist.Add(v);
                }
            }

            list = newlist;
        }

        /// <summary>
        /// 排序
        /// </summary>
        private void Sort()
        {
            list.Sort((Method x, Method y) => 
            {
                return (x.order > y.order) ? 1 : -1;
            });
        }

        /// <summary>
        /// 移除失效项
        /// </summary>
        public void Remove(object obj = null)
        {
            List<Method> newlist = new List<Method>();

            foreach (Method v in list)
            {
                if (v.method.IsStatic)
                {
                    newlist.Add(v);
                    continue;
                }

                if (v.instance != obj)
                {
                    newlist.Add(v);
                }
            }

            list = newlist;
        }

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="objs">参数列表</param>
        /// <returns>返回最后一个方法的返回值</returns>
        public object Invoke(object[] objs)
        {
            object ret = null;

            UWork.Do(UEvent.CMD_DO_START, this, objs);
            foreach (Method v in list)
            {
                try
                {
                    ret = v.method.Invoke(v.instance, objs);
                }
                catch (Exception e)
                {
                    UWork.Do(UEvent.CMD_DO_ERROR, v.method, objs, e);
                    ULog.Error(e);
                }
            }
            UWork.Do(UEvent.CMD_DO_END, this, objs, ret);
            return ret;
        }

        /// <summary>
        /// 获取方法的参数类型列表
        /// </summary>
        /// <returns></returns>
        public List<Type> GetMethodParamType()
        {
            List<Type> types = new List<Type>();

            if (list.Count == 0)
            {
                return types;
            }

            ParameterInfo[] param = list[0].method.GetParameters();

            if (param.Length == 0)
            {
                return types;
            }

            foreach (ParameterInfo v in param)
            {
                types.Add(v.ParameterType);
            }

            return types;
        }
    }
}